package com.ss.util;

/**
 * @Auther: ljy.s
 * @Date: 2022/9/20 - 09 - 20 - 13:32
 */

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.context.annotation.Bean;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 解析Excel表格工具类
 */
public class ExcelUtil {

    public static <T> List<T> readExcel(FileInputStream stream, Class<T> clazz) throws Exception {
        List<T> result = new ArrayList<>();
        // 1.从输入流中获取工作簿
        XSSFWorkbook workbook = new XSSFWorkbook(stream);
        // 2.在工作簿中获取目标工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 3.获取工作表中的行数
        int rowNum = sheet.getPhysicalNumberOfRows();
        // 4.获取第一行数据，因为Excel表格中第一行数据包含对应的要映射的属性
        Row row = sheet.getRow(0);
        // 5.遍历第一行数据，遍历出的数据就是当前实体类所需要的新增数据的所有属性，并且把这些数据放到key集合中
        List<String> key = new ArrayList<>();
        // 6.遍历第一行数据，遍历出所有要新增数据的属性，并且把数据放入到key集合中
        for (Cell cell : row) {
            cell.setCellType(Cell.CELL_TYPE_STRING);
            key.add(cell.getStringCellValue());
        }
        // 7.遍历所有的正式数据，但是要跳过第二行标题数据，所以要从下标2开始获取
        for (int i = 2; i < rowNum; i++) {
            // 8.获取所有行
            row = sheet.getRow(i);
            if (row != null) {
                // 9.遍历所有单元格中的数据，并且把key和value（单元格的数据），放入到excelMap中进行映射
                // 计数器j用于映射数据使用
                int j = 0;
                // 用于保存每条数据的Map，并且在Map中建立属性与对应数据的映射关系
                Map<String, String> excelMap = new HashMap<>();
                for (Cell cell : row) {
                    if (cell != null) {
                        // 10.把所有单元格中的数据设置为String
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        // 11.获取所有单元格数据
                        String value = cell.getStringCellValue();
                        if (value != null && !value.equals("")) {
                            // 12.将每个单元格的数据存储到集合中
                            excelMap.put(key.get(j), value);
                            j++;
                        }
                    }
                }
                // 13.创建对应的实体类类型
                T t = clazz.newInstance();
                /**
                 * spring提供的BeanMap，它可以通过反射的形式把Map中的数据映射到实体类中
                 */
                BeanMap beanMap = BeanMap.create(t);
                beanMap.putAll(excelMap);
                result.add(t);
            }
        }
        return result;
    }
}
